package com.orange.core.config.convert;

import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.orange.core.pojo.entity.IIdModel;
import com.orange.core.util.SpringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@SuppressWarnings({"unchecked", "rawtypes"})
@Slf4j
@RequiredArgsConstructor
@Component
public class IdToEntityConverterFactory implements ConverterFactory<String, Serializable> {

    private static final Map<Class<?>, Converter> CONVERTER_MAP = new ConcurrentHashMap<>();

    private final ApplicationContext applicationContext;

    @NonNull
    @Override
    public <T extends Serializable> Converter<String, T> getConverter(@NonNull Class<T> targetType) {
        return CONVERTER_MAP.computeIfAbsent(targetType, k -> new IdToEntityConverter(targetType));
    }

    private class IdToEntityConverter<T extends Serializable> implements Converter<String, T> {
        private final Class<T> clazz;

        public IdToEntityConverter(Class<T> clazz) {
            this.clazz = clazz;
        }

        @Override
        public T convert(@NonNull String source) {
            if (IIdModel.class.isAssignableFrom(clazz)) {
                String[] beanNames = SpringUtil.getBeanNamesForType(BaseMapper.class, clazz);
                if (ArrayUtil.isEmpty(beanNames)) {
                    log.error("{}类未找到", clazz.getSimpleName());
                    throw new RuntimeException("服务器好像出错了，请联系管理员。");
                }
                BaseMapper<T> mapper = (BaseMapper<T>) applicationContext.getBean(beanNames[0]);
                T t = mapper.selectById(Integer.parseInt(source));
                if (t == null) {
                    log.warn("id：{}，类：{}，数据不存在", source, clazz);
                    return null;
                } else {
                    return t;
                }
            }
            return (T) source;
        }
    }
}
